	// Class oRainFoxDoc
	//		- manejador de documentos
	function oRainFoxDoc(doc,drivers)
	{
		// ---------------------------------------------------------------
		// Guardamos el document actual
		this.DOC = doc;				// Documento actual
		this.drivers = drivers;		// Drivers que obtienen gotas de palabras
		this.drops = [];			// Gotas en la cola para caer
		this.num_drops = 0;			// Número de gotas en el documento
		this.INTERVAL_DRIP = null;	// Interval de goteo
		this.MAX_DRIPS_PER_DOC = Math.round(parseInt(doc.body.offsetHeight) / RFC_DRIPS_DENSITY) + 1;
																// Número de gotas a la vez por documento
		this.locked = false;		// Bloqueo de todas las gotas (permanecen inmóbiles)
		this.driver_id = 0;
		this.driver_count = 0;
		
		// ---------------------------------------------------------------
		// Funcion set_css: Mete estilo CSS para las gotas en el documento
		this.set_css = function()
		{
			var s = "";
			s+="div.rainfox_main { display:inline; background:transparent; padding:0px; max-width:300px; z-index:999; position:absolute; } \n";

			s+="img.rainfox_drop { max-width:16px; float:left; opacity:"+RFC_OPACITY+"; margin:3px; } \n";

			s+="div.rainfox_cont { background:#ffd; position:relative; margin:0px; float:left; display:none; border:1px solid #000; padding:0px; } \n";

			s+="img.rainfox_icon { max-width:16px; vertical-align:middle; } \n";
			s+="img.rainfox_iconlock {cursor:pointer; vertical-align:middle; } \n";

			s+="a.rainfox_title { margin-left:3px; font-family:verdana; font-size:12px; color:#000; font-weight:bold; text-decoration:none; border-bottom:1px none #000; } \n";
			s+="a:hover.rainfox_title { border-bottom:1px dotted #f00; } \n";
			s+="div.rainfox_title { padding:6px; width:100%; vertical-align:middle; } \n";

			s+="div.rainfox_html { border-top:1px solid #000; background:#fff; padding:4px; max-height:300px; overflow:auto; font-family:verdana; font-size:14px; } \n";
			s+="div.rainfox_html a { color:#a00; text-decoration:none; } \n";
			s+="div.rainfox_html a:hover { text-decoration:underline; color:#f00; } \n";

			//var so = dom_create('style');
			//so.innerHTML = s;
			var so = RF_DOM.create({
				tag: 'style',
				inner: s
			});
			this.DOC.getElementsByTagName('head')[0].appendChild(so);
		};
		this.set_css();
		
		// ---------------------------------------------------------------
		// Función get_drop: Obtiene una gota aleatoria de la lista de gotas
		this.get_drop = function()
		{
			if (this.drops.length == 0) return null;
			
			var drop = null;
			while (!drop)
			{
				//var i = get_random(this.drops.length);
				var i = RF_MATH.random(this.drops.length);
				if (i>=0 && i<this.drops.length)
				{
					drop = this.drops[i];
					// Se rehace el array
					var na = [];
					for (var idx=0; idx<this.drops.length; idx++)
						if (idx!=i)
							na.push(this.drops[idx]);
					this.drops = na;
				}
			}
			return drop;
		};
		
		// ---------------------------------------------------------------
		// Función add: Añade una gota a la cola
		this.add = function(drop)
		{
			if (!this.drops || !this.drops.length)
			{
				this.drops = [drop];
			}
			else
			{
				this.drops.push(drop);
			}
		};
		
		// ---------------------------------------------------------------
		// Manejador de respuestas XMLHttpRequest (función getajax)
		// NEW: RF_AJAX.onloadtext
		this.ajaxfunction = function(o)
		{
			// Obtenemos el driver que se está tratando actualmente
			var driver = this.drivers[this.driver_id];
			// Llamamos al driver para obtener las gotas
			var drops = driver.driver(o,this.DOC);
			// Añadimos cada gota al array de gotas globales
			for (var i=0; i<drops.length; i++)
			{
				this.add( make_drop({
					icon:		driver.icon,
					title: 		driver.title,
					home:		driver.home,
					href:		drops[i].href,
					html:		drops[i].html
				}, this) );
			}

			// Hacemos llover
			oRainFox.drip();
			
			// Vamos a por el nuevo driver
			this.driver_id++;
			if (this.driver_id <= this.drivers_count)
			{
				// Obtenemos la web del siguiente driver
				this.get_driver();
			}
		};
		
		// ---------------------------------------------------------------
		// Se obtiene la información del driver, y se solicita la página web por ajax (getajax)
		this.get_driver = function()
		{
			var driver = this.drivers[this.driver_id];
			
			// Obtenemos parametros para hacer la consulta
			var url = RF_STRING.replace(driver.location,'{WORD}',this.q);
			var url = RF_STRING.replace(url,'{WORD+}',this.qs);
			var url = RF_STRING.replace(url,'{WORD-}',this.qwo);
			var params = RF_STRING.replace(driver.query,'{WORD}',this.q);
			var params = RF_STRING.replace(params,'{WORD+}',this.qs);
			var params = RF_STRING.replace(params,'{WORD-}',this.qwo);
			if (driver.method == 'get')
			{
				url += "?"+params;
				params = null;
			}
			// Obtenemos la página web (se obtiene en this.ajaxfunction)
			//getajax(url,this,params);
			RF_AJAX.request({
				url: url,
				params: params,
				method: driver.method,
				onloadtext: this
			});
		};
		
		
		
		// ---------------------------------------------------------------
		// Función rain: obtiene gotas de una palabra, y comienza a llover
		this.rain = function(word)
		{
			// Palabra a buscar
			this.q = escape(RF_STRING.trim(word));
			if (!this.q || !this.q.length) return;
			this.qs = RF_STRING.replace(this.q,' ','+'); // Sustituye espacios por +
			this.qwo = RF_STRING.replace(this.q,' ',''); // Quita los espacios
			
			// Se establecen los parámetros para recorrer los drivers
			this.driver_id = 0;
			this.drivers_count = this.drivers.length - 1;
			
			// Se llama al primer driver
			this.get_driver();
		};
	}

// ###################################################################################
	
	// Crea una gota
	function make_drop(o,raindoc)
	{
		// ------------------------------------------------------------------
		// En este DIV se mete el icono que cae (gota) y el contenido
		//var main = dom_create('div');
		//main.className = 'rainfox_main';
		var main = RF_DOM.create({
			tag: 'div',
			classname: 'rainfox_main'
		});
		// bloqueo de gota
		main.locked = false;
		
		// ------------------------------------------------------------------
		// imagen-icono (gota)
		/*
		var drop = dom_create('img');
		drop.className = 'rainfox_drop';
		drop.src = o.icon;
		drop.border = '0';
		*/
		var drop = RF_DOM.create({
			tag: 'img',
			classname: 'rainfox_drop',
			src: o.icon,
			border: '0'
		});
		
		// ------------------------------------------------------------------
		// DIV con el contenido de la gota
		//var cont = dom_create('div');
		//cont.className = 'rainfox_cont';
		var cont = RF_DOM.create({
			tag: 'div',
			style: 'text-align:left; -moz-border-radius:3%; padding:3px; ',
			classname: 'rainfox_cont'
		});
		
		// DIV con el titulo del contenido
		//var dtitle = dom_create('div');
		//dtitle.className = 'rainfox_title';
		var dtitle = RF_DOM.create({
			tag: 'div',
			classname: 'rainfox_title'
		});
		
		// Enlace con el icono del titulo
		//var aicon = dom_create('a');
		//aicon.href = o.href;
		var aicon = RF_DOM.create({
			tag: 'a',
			style: 'float:left; ',
			href: o.href
		});
		
		// Icono del titulo
		//var icon = dom_create('img');
		//icon.className = 'rainfox_icon';
		//icon.src = o.icon;
		//icon.border = '0';
		var icon = RF_DOM.create({
			tag: 'img',
			classname: 'rainfox_icon',
			src: o.icon,
			border: '0'
		});
		
		/*
		// http://www.formatoweb.com.ar/blog/2007/09/22/drag-drop-arrastrar-y-soltar-simple-en-un-div-con-javascript-sin-librerias/
		
		// Icono de drag'n'drop
		var icon_dragdrop = RF_DOM.create({
			tag: 'img',
			classname: 'rainfox_dragdrop',
			style: 'float:right; ',
			src: 'chrome://rainfox/skin/candado-abierto.png'
		});
		icon_dragdrop.main = main;
		icon_dragdrop.addEventListener("mousedown", function(event){
				var id = this.id;
			    elMovimiento = this;

			    // Obtengo la posicion del cursor
		        cursorComienzoX = event.clientX + window.scrollX;
		        cursorComienzoY = event.clientY + window.scrollY;
		        
		        document.addEventListener("mousemove", function(event){
		        	    var xActual, yActual;
	        	        
		        	    xActual = event.clientX + window.scrollX;
	        	        yActual = event.clientY + window.scrollY;

	        	        elMovimiento.style.left = (elComienzoX + xActual - cursorComienzoX) + "px";
		        	    elMovimiento.style.top = (elComienzoY + yActual - cursorComienzoY) + "px";

		        	    evitaEventos(event);
		        }, true);
		        
		        document.addEventListener("mouseup", function(event){
					document.removeEventListener("mousemove", enMovimiento, true);
					document.removeEventListener("mouseup", finMovimiento, true);
		        }, true);
		        
			    elComienzoX = parseInt(elMovimiento.style.left);
			    elComienzoY = parseInt(elMovimiento.style.top);
			    // Actualizo el posicion del elemento
			    elMovimiento.style.zIndex = ++posicion;
			    evitaEventos(event);
			}
		},false);
		*/
		
		
		// Icono del candado
		var icon_lock = RF_DOM.create({
			tag: 'img',
			classname: 'rainfox_iconlock',
			style: 'float:right; ',
			src: 'chrome://rainfox/skin/candado-abierto.png'
		});
		icon_lock.main = main;
		icon_lock.addEventListener("click", function(){
			if (icon_lock.main.locked) {
				icon_lock.src = 'chrome://rainfox/skin/candado-abierto.png';
				icon_lock.main.locked = false;
			} else {
				icon_lock.src = 'chrome://rainfox/skin/candado-cerrado.png';
				icon_lock.main.locked = true;
			}
		},false);
		
		// Icono eliminar gota
		var icon_delete = RF_DOM.create({
			tag: 'img',
			style: 'cursor:pointer; vertical-align:middle; float:right; margin-right:8px; ',
			src: 'chrome://rainfox/skin/cerrar.png'
		});
		icon_delete.main = main;
		icon_delete.addEventListener("click", function(){
			// Se elimina la gota
			icon_delete.main.locked = true;
			drop_die(icon_delete.main, true);
		},false);
		
		// Se añade el icono al enlace
		aicon.appendChild(icon);
		// Se añade el icono de eliminacion
		dtitle.appendChild(icon_delete);
		// Se añade el icono de bloqueo al título
		dtitle.appendChild(icon_lock);
		// Se añade el icono-enlace al titulo
		dtitle.appendChild(aicon);
		
		// Se crea un enlace a la home del buscador
		//var ahome = dom_create('a');
		//ahome.className = 'rainfox_title';
		//ahome.href = o.home;
		//ahome.innerHTML = o.title;
		var ahome = RF_DOM.create({
			tag: 'a',
			classname: 'rainfox_title',
			href: o.home,
			inner: o.title
		});
		
		// Se añade el título a la barra de título
		dtitle.appendChild(ahome);
		// Se añade la barra de título al contenido
		cont.appendChild(dtitle);
		// Se crea el DIV con el HTML de la gota
		//var divhtml = dom_create('div');
		//divhtml.className = 'rainfox_html';
		//divhtml.innerHTML = o.html;
		var divhtml = RF_DOM.create({
			tag: 'div',
			classname: 'rainfox_html',
			style: 'font-size:12px; ',
			inner: o.html
		});
		// Se añade el html al contenido
		cont.appendChild(divhtml);
		
		// ------------------------------------------------------------------
		// Se añade la gota al main
		main.appendChild(drop);
		// Se añade el contenido al main
		main.appendChild(cont);
		
		// ------------------------------------------------------------------
		// Se establecen los objetos
		main.DROP = drop;
		main.CONT = cont;
		drop.MAIN = main;
		cont.MAIN = main;
		main.RAINDOC = raindoc; // raindoc es el objeto RainFoxDoc al que pertenece la gota
		
		// ------------------------------------------------------------------
		// Se añaden los eventos
		// Cuando el ratón pasa por encima de la gota, se muestra el contenido y se oculta la gota
		main.addEventListener("mouseover", function(){
			drop.style.display = 'none';
			cont.style.display = 'inline';
		}, false);
		// Cuando el ratón sale del main, se oculta el contenido, y se muestra la gota
		main.addEventListener("mouseout", function(){
			if (main.locked) return;
			cont.style.display = 'none';
			drop.style.display = 'inline';
		},false);
		
		//alert(main);
		
		// ------------------------------------------------------------------
		// Se devuelve el objeto
		return main;
	}

// ###################################################################################

	function drop_die(o, fadeout) {
		// Drop died
		// Se deja de mover la gota (muere)
		if (o.INTERVAL)
			clearInterval(o.INTERVAL);
		if (fadeout) {
			// Se hace un fadeout
			var checkopacity = parseFloat(o.style.opacity);
			if (checkopacity!=1) o.style.opacity = 1;
			o.FADEOUTINTERVAL = setInterval(function(){
				var opacity = parseFloat(o.style.opacity);
				opacity -= .2;
				if (opacity <= 0) {
					clearInterval(o.FADEOUTINTERVAL);
					// Se elimina la gota
					o.parentNode.removeChild(o);
					// Se le indica a RainFox que hay una gota menos en el documento
					o.RAINDOC.num_drops--;
					// Se le pide a RainFox que caiga otra gota
					oRainFox.drip();
				}
				o.style.opacity = opacity;
			},60);
		} else {
			// Se elimina la gota
			o.parentNode.removeChild(o);
			// Se le indica a RainFox que hay una gota menos en el documento
			o.RAINDOC.num_drops--;
			// Se le pide a RainFox que caiga otra gota
			oRainFox.drip();
		}
	}

	function drop_fall(o)
	{
		// o = main
		
		// Se establecen las propiedades
		o.BORN = true;
		o.TIMEOUT = null;
		o.FALLING = true;
		o.SPEED = RFC_SPEED + RF_MATH.random(25);

		// Cuando el ratón pase por encima de la gota, entonces deja de caer		
		o.addEventListener("mouseover", function()
		{
			// Si hubiera un timeout para continuar la caida, se cancela
			if (o.TIMEOUT)
			{
				clearTimeout(o.TIMEOUT);
				o.TIMEOUT = null;
			}
			// La gota se hace opaca (visible)
			o.DROP.style.opacity = 1;
			// Deja de caer
			o.FALLING = false;
		}, false);
		
		// Cuando el ratón sale fuera de "main", a los pocos instantes la gota vuelve a caer
		o.addEventListener("mouseout", function()
		{
			// Se reanuda la caida a los pocos instantes (RFC_RESTART_DELAY)
			o.TIMEOUT = setTimeout(function(){
				// La gota se vuelve translúcida
				o.DROP.style.opacity = RFC_OPACITY;
				// Bandera de caida activa
				o.FALLING = true;
			},RFC_RESTART_DELAY);
		}, false);
		
		// Se le da movimiento a la gota
		o.INTERVAL = setInterval(function()
		{
			// Si la bandera de caida no está activa, se sale (no cae)
			// RAINFOX.locked hace que todas las gotas permanezcan inmóbiles
			if (!o.FALLING || o.locked || o.RAINDOC.locked) return;
			// Se incrementa la posición Y de la gota
			o.TOP += RFC_Y_OFFSET;
			// Se baja la gota
			o.style.top = o.TOP + 'px';
			// Se comprueba si la gota cayó al suelo
			var mh = o.offsetTop + o.offsetHeight;
			var dh = o.RAINDOC.DOC.body.clientHeight;
			//var dh = 2000;
			//if (o.TOP > RFC_Y_OUT)
			if (mh > dh) {
				drop_die(o);
				/*
				// Drop died
				// Se deja de mover la gota (muere)
				clearInterval(o.INTERVAL);
				// Se elimina la gota
				o.parentNode.removeChild(o);
				// Se le indica a RainFox que hay una gota menos en el documento
				//oRainFox.drops--;
				o.RAINDOC.num_drops--;
				// Se le pide a RainFox que caiga otra gota
				oRainFox.drip();
				//o.RAINDOC.drip();
				*/
			}
		},o.SPEED);
	}		
		
		
		
